--
-- Author: shunguo.chen
-- Date: 2019-05-17 16:49:20
--
-- LegendVo   传奇武器vo
--

local Item = require("app.public.dao.Item")
local Daibi = require("app.public.dao.Daibi")
local Skill = require("app.public.dao.Skill")
local LegendFashion = import(".LegendFashion")

local fileName = string.getModeName(...)
local ClassRef = class(fileName)

function ClassRef:ctor(data)
    if data then
        self:init(data)
    end
end

-- conf   legend表配置
function ClassRef:init(conf)
    self._conf = conf

    self.id = tonumber(conf.ID)
    self.order = tonumber(conf.order or 1)
    self.classId = tonumber(conf.class)
    self.specId = tonumber(conf.masterID)
    self.skillNumMax = tonumber(conf.skillNum)

    self._isOpen = (conf.open == "1")

    -- coreSkill
    self._coreSkillParams = string.splitTwice(conf.legendTalentSkill, nil, true)

    -- 技能组Id，{{teamId, costNum, teamId}, ...}
    local skillParams = string.splitTwice(conf.legendSkills, nil, true)
    for i,param in ipairs(skillParams) do
        param[3] = GD:getLegendSkillTeam(param[1])
    end
    self._skillParams = skillParams

    -- dump(self._coreSkillParams, "_coreSkillParams")
    -- dump(self._skillParams, "_skillParams")

    -- fashion
    local fashionConfs = GD:getLegendFashionConfs(self.id)
    local fashions = {}
    for i,conf in ipairs(fashionConfs) do
        local fashion = LegendFashion.new(conf)
        fashions[#fashions + 1] = fashion
    end
    self.fashions = fashions

    self._isWear = false
    self._isNew = false
end

-- message Legend {
--     int32 ID                                                    =   1;  //神器ID
--     int32 Level                                             =   2;  //神器等级
--     int32 Exp                                                   = 3;    //神器当前经验值
--     int32 SkillPoints                                   = 4;    //神器剩余的技能点数
--     int32 LegendTalentSkill                     = 5;    //神器天赋技能ID
--     repeated int32 LegendSkills             = 6;    //神器拥有的技能,该数据无序
--     repeated int32 LegendSkillsChosen   = 7;    //神器拥有的技能,该数据无序
--     repeated int32 FashionIDs                   = 8;    //神器拥有的时装ID,该数据无序
--     //int32 WearingFashion                          = 9;    //神器当前穿戴的外观
-- }
function ClassRef:initMsg(msg)
    self._isActive = (msg ~= nil)
    self.coreSkill = nil
    self.coreNextSkill = nil
    self._coreSkillLv = 1
    self._chooseLegendSkillTeams = {} -- 选择的神器技能组
    self._openLegendSkillTeams = {} -- 开启的神器技能组
    self._isNewFashion = false -- 当前是新获得外显

    if msg then
        self.lv = msg.Level
        self.exp = msg.Exp
        self.skillPoint = msg.SkillPoints

        -- 核心技能
        local skill = Skill.new()
        skill:read({uid=msg.LegendTalentSkill})
        self.coreSkill = skill

        for i,param in ipairs(self._coreSkillParams) do
            if msg.LegendTalentSkill == param[2] then
                self._coreSkillLv = i
                break
            end
        end

        if not self:isCoreSkillLvMax() then
            local nextSkillId = self._coreSkillParams[self._coreSkillLv + 1][2]
            skill = Skill.new()
            skill:read({uid=nextSkillId})
            self.coreNextSkill = skill
        end

        for i,v in ipairs(msg.LegendSkillsChosen) do
            self._chooseLegendSkillTeams[i] = v
        end
        for i,v in ipairs(msg.LegendSkills) do
            self._openLegendSkillTeams[i] = v
        end

        -- 设置时装激活状态
        local fashionLv
        local fashionActiveDict = {}
        for i,id in ipairs(msg.FashionIDs or {}) do
            fashionActiveDict[id] = true
        end
        for i,fashion in ipairs(self.fashions) do
            if fashionActiveDict[fashion.id] then
                fashion:setActive(true)
                fashionLv = i
            end
        end
        fashionLv = fashionLv or 1
        self._showFashion = self.fashions[math.min(fashionLv, #self.fashions)]
    else
        -- 没有服务器数据，构造出来
        self.lv = 1
        self.exp = 0
        self.skillPoint = 0

        -- 获得配置的第一个技能
        local firstSkillId = self._coreSkillParams[1][2]
        local skill = Skill.new()
        skill:read({uid=firstSkillId})
        self.coreSkill = skill

        self._showFashion = self.fashions[1]
    end

    self:_initLvExpMax()

    -- dump(self, "LegendVo", 3)
    -- dump(self._showFashion, "LegendVo._showFashion")
end

function ClassRef:getId()
    return self.id
end

function ClassRef:getLv()
    return self.lv
end

-- 神器等级经验更新
function ClassRef:updateLvExp(lv, exp, legend)
    if legend then
        self:initMsg(legend)
    else
        local preLv = self.lv
        self.lv = lv
        self.exp = exp

        if preLv ~= self.lv then
            self:_initLvExpMax()
        end
    end
end

-- 模拟添加经验
function ClassRef:addExp(exp)
    local expNew = self.exp + exp
    if expNew >= self.expMax then
        self.lv = self.lv + 1
        self.exp = expNew - self.expMax
        self:_initLvExpMax()
    else
        self.exp = expNew
    end
    return self.exp, self.lv, self.expMax
end

-- 神器外显激活
function ClassRef:updateFashion(fashion)
    fashion:setActive(true)
    self._showFashion = fashion
end

-- 重置所有技能
function ClassRef:resetSkills(skillPoint)
    self.skillPoint = skillPoint
    self._chooseLegendSkillTeams = {}
    self._openLegendSkillTeams = {}
    if self._skills then
        for i,skill in ipairs(self._skills) do
            if skill:isLegendChoose() then
                skill:setLegendChoose(false)
            end
            if skill:isLegendOpen() then
                skill:setLegendOpen(false)
            end
        end
    end
end

-- 激活技能
function ClassRef:activeSkill(skill)
    self.skillPoint = self.skillPoint - 1
    skill:setLegendOpen(true)
    table.insert(self._openLegendSkillTeams, skill:getLegendTeam())
end

-- 更新技能选择状态
function ClassRef:updateSkill(skill)
    local isChoose = skill:isLegendChoose()
    local legentTeam = skill:getLegendTeam()
    skill:setLegendChoose(not isChoose)
    if isChoose then
        table.removebyvalue(self._chooseLegendSkillTeams, legentTeam)
    else
        table.insert(self._chooseLegendSkillTeams, legentTeam)
    end
end

function ClassRef:_initLvExpMax()
    local conf = GD:getLegendLvConf(self.lv)
    self.expMax = tonumber(conf.exp or 0)
end

function ClassRef:isMaxLv()
    return self.expMax == 0
end

function ClassRef:isSkillFull()
    return #self._chooseLegendSkillTeams == self.skillNumMax
end

-- 是否需要重置，使用过经验道具就需要重置
function ClassRef:isNeedReset()
    return self.exp > 0 or self.lv > 1
end

-- 有技能开启
function ClassRef:hasOpenSkill()
    return #self._openLegendSkillTeams > 0
end

-- 有技能点未使用/isNew -》神器有红点
function ClassRef:hasRedPoint()
    return self.skillPoint > 0 or self._isNew
end

function ClassRef:getCoreSkillLv()
    return self._coreSkillLv
end

function ClassRef:getShowFashion()
    return self._showFashion
end

function ClassRef:getShowAvatarParam()
    return self._showFashion:getAvatarParam()
end

function ClassRef:getAvatarOffsetPos()
    if not self._offsetPos then
        local posStr = self._conf.position
        if posStr then
            local ary = string.splitTwice(posStr, nil, true)
            self._offsetPos = ary[1]
            self._offsetPosEx = ary[2]
        end

        if not self._offsetPos then
            self._offsetPos = {0,0}
        end

        -- 刺客有两件avatar
        if not self._offsetPosEx and self:getClass() == 4 then
            self._offsetPosEx = {0,0}
        end
    end
    return self._offsetPos, self._offsetPosEx
end

function ClassRef:getShowFashionIcon()
    return self._showFashion:getIcon()
end

function ClassRef:hasFashion()
    return self._showFashion:isActive()
end

-- 获得下一个需要开启的外显
function ClassRef:getNextActiveFashion()
    if self._showFashion:isActive() then
        local showLv = self._showFashion.lv
        if showLv < #self.fashions then
            return self.fashions[showLv + 1]
        end
    else
        return self._showFashion
    end
end

-- 来源参数
function ClassRef:getResourceParam()
    if not self._resourceParam then
        local conf = GD:queryItemById(self._conf.itemID)
        local resourceStr = GD:getConvertResource(conf.getResource, Enums.ItemBagType.item, tonumber(conf.ID))
        if resourceStr then
            local resources = string.split( resourceStr, ";" )
            local resource = resources[1]
            local ary = string.split( resource, "|" )
            local featureId = tonumber( ary[1] )
            local param = string.split(ary[3], "#")
            self._resourceParam = {feature=featureId, param=param}
        end
    end
    return self._resourceParam
end

function ClassRef:clearSkills()
    self._skills = nil
end

-- 普通技能
function ClassRef:getSkills()
    if not self._skills then
        local skills = {}
        local legendTeam, costNum, skillTeam, skill, skillId
        for i,param in ipairs(self._skillParams) do
            legendTeam = param[1]
            costNum = param[2]
            skillTeam = param[3]
            if skillTeam and skillTeam > 0 then
                skill = UD:getSkillByTeam(skillTeam)
                if not skill then
                    local conf = GD:getFirstSkillConfByTeam(skillTeam)
                    skill = Skill.new()
                    skill:read({uid=tonumber(conf.ID)})
                end
                skill:setLegendParam(legendTeam, costNum)
                skills[#skills + 1] = skill
            end
        end
        self._skills = skills
    end

    for i,skill in ipairs(self._skills) do
        if table.indexof(self._chooseLegendSkillTeams, skill:getLegendTeam()) then
            skill:setLegendChoose(true)
        else
            skill:setLegendChoose(false)
        end
    end

    for i,skill in ipairs(self._skills) do
        if table.indexof(self._openLegendSkillTeams, skill:getLegendTeam()) then
            skill:setLegendOpen(true)
        else
            skill:setLegendOpen(false)
            skill:setLegendSkillPoint(self.skillPoint)
        end
    end

    table.sort(self._skills, function(a, b)
        local isOpen_a = a:isLegendOpen()
        local isOpen_b = b:isLegendOpen()
        if isOpen_a == isOpen_b then
            return a:getId() < b:getId()
        else
            return isOpen_a
        end
    end)

    return self._skills
end

-- 选中的技能
function ClassRef:getChooseSkills()
    local chooseSkills = {}
    if #self._chooseLegendSkillTeams > 0 then
        local skills = self:getSkills()
        for i,skill in ipairs(skills) do
            if skill:isLegendChoose() then
                chooseSkills[#chooseSkills + 1] = skill
            end
        end
    end
    return chooseSkills
end

function ClassRef:isCoreSkillLvMax()
    return self._coreSkillLv == #self._coreSkillParams
end

function ClassRef:getNextCoreSkillNeedLv()
    if not self:isCoreSkillLvMax() then
        return self._coreSkillParams[self._coreSkillLv + 1][1]
    end
end

-- 经验道具
function ClassRef:getExpCostItem()
    if not self._expCostItem then
        local itemId = tonumber(GD:getSystemPar("legendExpItemID"))
        local item = Item.new(Enums.ItemBagType.item)
        item:read({tid=itemId, amount=0})
        self._expCostItem = item
    end
    local itemAmount = UD:getItemAmountByTid(self._expCostItem:getId())
    self._expCostItem:setAmount(itemAmount)
    return self._expCostItem
end

-- 重置等级消耗道具
function ClassRef:getResetExpCostItem()
    if not self._resetExpCostItem then
        local itemStr = GD:getSystemStrPar("legendRecycleExpCost")
        self._resetExpCostItem = UD:parseItemFromString(itemStr)
    end
    return self._resetExpCostItem
end

-- 重置消耗道具
function ClassRef:getResetSkillCostItem()
    if not self._resetSkillCostItem then
        local itemStr = GD:getSystemStrPar("legendRecycleSkillCost")
        self._resetSkillCostItem = UD:parseItemFromString(itemStr)
    end
    return self._resetSkillCostItem
end

-- 获得当前等级获得过的所有经验值
function ClassRef:_getTotalExp()
    local totalExp = self.exp
    if self.lv > 1 then
        for i=1, self.lv-1 do
            local conf = GD:getLegendLvConf(i)
            totalExp = totalExp + tonumber(conf.exp)
        end
    end
    return totalExp
end

-- 计算回收获得经验道具，需要计算当前经验值，然后按每个经验道具所包含经验值计算出数量
function ClassRef:getResetExpGotItem()
    if not self._resetExpGotItem then
        local itemId = tonumber(GD:getSystemPar("legendExpItemID"))
        local item = Item.new(Enums.ItemBagType.item)
        item:read({tid=itemId, amount=0})
        self._resetExpGotItem = item
    end

    local perExp = tonumber(self._resetExpGotItem:getUseValue())
    local totalExp = self:_getTotalExp()
    self._resetExpGotItem:setAmount(math.ceil(totalExp / perExp))

    return self._resetExpGotItem
end
-- 技能回收获得消耗的技能点
function ClassRef:getResetSkillGotItem()
    if not self._resetSkillGotItem then
        local item = Daibi.new()
        item:read({tid=Constant.Legend_SkillPoint, amount=0})
        self._resetSkillGotItem = item
    end
    self._resetSkillGotItem:setAmount(#self._openLegendSkillTeams)
    return self._resetSkillGotItem
end

function ClassRef:isOpen()
    return self._isOpen
end

-- 新获得
function ClassRef:setIsNew(b)
    self._isNew = b
end
function ClassRef:isNew()
    return self._isNew
end

-- 激活
function ClassRef:setActive(b)
    self._isActive = b
end
function ClassRef:isActive()
    return self._isActive
end

-- 穿戴
function ClassRef:setWear(b)
    self._isWear = b
end
function ClassRef:isWear()
    return self._isWear
end

function ClassRef:getName()
    return L(self._conf.name)
end

function ClassRef:getClass()
    return tonumber(self._conf.class)
end

function ClassRef:getIcon()
    if not self._icon then
        self._icon = table.concat({"art/legend/", self._conf.picTalentSkill, ".png"})
    end
    return self._icon
end

function ClassRef:getSpecId()
    return self.specId
end

-- 专精名字
function ClassRef:getSpecName()
    if not self._specName then
        local specConf = GD:getSpec_typeConfig(self.specId)
        self._specName = L(specConf.nameDes)
    end
    return self._specName
end

return ClassRef